﻿using LightCAD.MathLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static LightCAD.MathLib.Constants;


namespace LightCAD.Three
{
    public class WebGLCubeRenderTarget : WebGLRenderTarget
    {
        public class Shader
        {
            public Uniforms uniforms;
            public string vertexShader;
            public string fragmentShader;
        }
        public readonly ListEx<Image> images;
        public WebGLCubeRenderTarget(int size = 1, RenderTargetOptions options = null) : base(size, size, options)
        {

            this.images = new ListEx<Image> { image, image, image, image, image, image };

            if (options == null)
            {
                this.texture = new CubeTexture(images);
                options = new RenderTargetOptions();
            }
            else
                this.texture = new CubeTexture(images, options.mapping, options.wrapS, options.wrapT, options.magFilter.Value, options.minFilter.Value, options.format, options.type, options.anisotropy, options.encoding);

            this.texture.isRenderTargetTexture = true;

            this.texture.generateMipmaps = options.generateMipmaps != null ? options.generateMipmaps.Value : false;
            this.texture.minFilter = options?.minFilter != null ? options.minFilter.Value : LinearFilter;

        }
        public WebGLCubeRenderTarget fromEquirectangularTexture(WebGLRenderer renderer, Texture texture)
        {

            this.texture.type = texture.type;
            this.texture.encoding = texture.encoding;

            this.texture.generateMipmaps = texture.generateMipmaps;
            this.texture.minFilter = texture.minFilter;
            this.texture.magFilter = texture.magFilter;

            var shader = new Shader
            {

                uniforms = new Uniforms {
                        {"tEquirect", new Uniform{ value= null } }
                    },
                vertexShader = /* glsl */@"
                        varying vec3 vWorldDirection;
				        vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
					        return Normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );

				        }
				        void main() {
					        vWorldDirection = transformDirection( position, modelMatrix );
					        #include <begin_vertex>
					        #include <project_vertex>
				        }
                    ",

                fragmentShader = /* glsl */@"
				        uniform sampler2D tEquirect;
				        varying vec3 vWorldDirection;
				        #include <common>
				        void main() {
					        vec3 direction = Normalize( vWorldDirection );
					        vec2 sampleUV = equirectUv( direction );
					        gl_FragColor = texture2D( tEquirect, sampleUV );
				        }"
            };

            var geometry = new BoxGeometry(5, 5, 5);

            var material = new ShaderMaterial
            {

                name = "CubemapFromEquirect",
                uniforms = UniformsUtils.cloneUniforms(shader.uniforms),
                vertexShader = shader.vertexShader,
                fragmentShader = shader.fragmentShader,
                side = BackSide,
                blending = NoBlending
            };

            material.uniforms["tEquirect"].value = texture;


            var mesh = new Mesh(geometry, material);

            var currentMinFilter = texture.minFilter;

            // Avoid blurred poles
            if (texture.minFilter == LinearMipmapLinearFilter) texture.minFilter = LinearFilter;

            var camera = new CubeCamera(1, 10, this);
            camera.update(renderer, mesh);

            texture.minFilter = currentMinFilter;

            mesh.geometry.dispose();
            mesh.material.dispose();

            return this;

        }

        public void clear(WebGLRenderer renderer, bool color, bool depth, bool stencil)
        {
            var currentRenderTarget = renderer.getRenderTarget();

            for (int i = 0; i < 6; i++)
            {
                renderer.setRenderTarget(this, i);
                renderer.clear(color, depth, stencil);
            }
            renderer.setRenderTarget(currentRenderTarget);
        }

    }
}
